package com.sparkseries.service.impl;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.sparkseries.common.util.exception.BusinessException;
import com.sparkseries.dao.SysMenuMapper;
import com.sparkseries.dao.SysRoleMapper;
import com.sparkseries.domain.SysMenu;
import com.sparkseries.domain.SysRole;
import com.sparkseries.domain.vo.SysMenuVO;
import com.sparkseries.domain.vo.SysRoleVO;
import com.sparkseries.dto.SysMenuDTO;
import com.sparkseries.enums.DefaultStatusEnum;
import com.sparkseries.service.SysMenuService;
import com.sparkseries.common.util.domain.Result;
import com.sparkseries.common.util.tool.ObjectConvertTool;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * 菜单管理
 */
@Slf4j
@Service
public class SysMenuServiceImpl implements SysMenuService {
    @Resource
    private SysMenuMapper sysMenuMapper;
    @Resource
    private SysRoleMapper sysRoleMapper;

    /**
     * 创建菜单
     * @param menuDTO 菜单传输类
     * @return 默认响应类
     */
    @Override
    public Result<?> createMenu(SysMenuDTO menuDTO) {
        validateMenuDTO(menuDTO);

        SysMenu sysMenu = convertToSysMenu(menuDTO);
        sysMenu.setId(IdWorker.getId());

        if (sysMenuMapper.createMenu(sysMenu) < 0) {
            log.error("菜单创建失败，菜单信息: {}", menuDTO);
            throw new BusinessException("菜单创建失败");

        }

        log.info("菜单创建成功，菜单ID: {}", sysMenu.getId());
        return Result.ok("菜单创建成功");
    }

    /**
     * 绑定菜单角色
     * @param roleIds 角色ID集合
     * @param menuId 菜单ID
     * @return 默认响应类
     */
    @Override
    public Result<?> bindMenuWithRole(List<Long> roleIds, Long menuId) {
        validateMenuId(menuId);
        validateRoleIds(roleIds);

        if (sysMenuMapper.bindMenuWithRole(roleIds, menuId) <= 0) {
            log.error("菜单角色绑定失败，菜单ID: {}，角色ID: {}", menuId, roleIds);
            throw new BusinessException("绑定失败");
        }

        log.info("菜单角色绑定成功，菜单ID: {}，角色ID: {}", menuId, roleIds);
        return Result.ok("绑定成功");
    }

    /**
     * 删除菜单
     * @param menuId 菜单ID
     * @return 默认响应类
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> deleteMenu(Long menuId) {
        validateMenuId(menuId);

        // 删除菜单绑定关系
        if (!sysMenuMapper.listRoleIdsByMenuId(menuId).isEmpty() && sysMenuMapper.deleteMenuBind(menuId) <= 0) {
            log.error("菜单绑定关系删除失败，菜单ID: {}", menuId);
            throw new BusinessException("菜单绑定关系删除失败");
        }

        // 删除菜单
        if (sysMenuMapper.deleteMenu(menuId) <= 0) {
            log.error("菜单删除失败，菜单ID: {}", menuId);
            throw  new BusinessException("菜单删除失败");
        }

        log.info("菜单删除成功，菜单ID: {}", menuId);
        return Result.ok("菜单删除成功");
    }

    /**
     * 删除菜单角色绑定
     * @param roleIds 角色ID集合
     * @param menuId 菜单ID
     * @return 默认响应类
     */
    @Override
    public Result<?> deleteBind(List<Long> roleIds, Long menuId) {
        validateMenuId(menuId);
        validateRoleIds(roleIds);

        Integer unBindCount = sysMenuMapper.deleteBind(roleIds, menuId);

        return Result.ok("已经删除了绑定的角色条数: " + unBindCount);
    }

    /**
     * 修改菜单
     * @param menuDTO 菜单传输类
     * @return 默认响应类
     */
    @Override
    public Result<?> updateMenu(SysMenuDTO menuDTO) {
        validateMenuDTO(menuDTO);
        validateMenuId(menuDTO.getId());

        SysMenu sysMenu = convertToSysMenu(menuDTO);
        if (sysMenuMapper.updateMenu(sysMenu) <= 0) {
            log.error("菜单修改失败，菜单信息: {}", menuDTO);
            return Result.error("修改失败");
        }

        log.info("菜单修改成功，菜单ID: {}", sysMenu.getId());
        return Result.ok("修改成功");
    }

    /**
     * 修改菜单状态
     * @param menuId 菜单ID
     * @param status 是否启用（0-禁用，1-启用）
     * @return 默认响应类
     */
    @Override
    public Result<?> updateMenuStatus(Long menuId, Integer status) {
        validateMenuId(menuId);
        validateStatus(status);

        if (sysMenuMapper.updateMenuStatus(menuId, status) <= 0) {
            log.error("菜单状态修改失败，菜单ID: {}，状态: {}", menuId, status);
            return Result.error("菜单状态修改失败");
        }

        log.info("菜单状态修改成功，菜单ID: {}，状态: {}", menuId, DefaultStatusEnum.getDesc(status));
        return Result.ok("菜单状态修改成功");
    }

    /**
     * 获取菜单列表
     * @param menuDTO 菜单传输类
     * @return 菜单响应类集合
     */
    @Override
    public Result<List<SysMenuVO>> listMenu(SysMenuDTO menuDTO) {
        validateMenuDTO(menuDTO);

        SysMenu sysMenu = convertToSysMenu(menuDTO);
        List<SysMenu> sysMenus = sysMenuMapper.listMenu(sysMenu);
        List<SysMenuVO> sysMenuVOS = ObjectConvertTool.originsConvert(sysMenus, SysMenuVO.class);

        return Result.ok("查询成功", sysMenuVOS);
    }

    /**
     * 获取菜单信息
     * @param menuId 菜单ID
     * @return 菜单响应类
     */
    @Override
    public Result<SysMenuVO> getMenuInfo(Long menuId) {
        return Optional.ofNullable(sysMenuMapper.getMenuById(menuId))
                .map(role -> {
                    log.debug("成功获取菜单信息，菜单ID: {}", menuId);
                    return Result.ok("查询成功", convertToSysMenuVO(role));
                })
                .orElseGet(() -> {
                    log.warn("未查询到该菜单，菜单ID: {}", menuId);
                    return Result.error("菜单信息未找到");
                });
    }

    /**
     * 获取菜单下的角色
     * @param menuId 菜单ID
     * @return 角色响应类集合
     */
    @Override
    public Result<List<SysRoleVO>> listRoleIdsByMenuId(Long menuId) {
        validateMenuId(menuId);

        List<Long> roleIds = sysMenuMapper.listRoleIdsByMenuId(menuId);
        if (Objects.isNull(roleIds) || roleIds.isEmpty()) {
            return Result.ok("该菜单未分配任何角色", null);
        }
        List<SysRole> roles = sysRoleMapper.getRolesByIds(roleIds);
        List<SysRoleVO> roleVOS = ObjectConvertTool.originsConvert(roles, SysRoleVO.class);

        return Result.ok("获取成功", roleVOS);
    }


    //------------------------ 参数校验 ------------------------
    private void validateMenuDTO(SysMenuDTO menuDTO) {
        if (Objects.isNull(menuDTO)) {
            throw new BusinessException("菜单信息不能为空");
        }
    }

    private void validateMenuId(Long menuId) {
        if (Objects.isNull(menuId) || menuId <= 0) {
            throw new BusinessException("角色ID无效");
        }
        if (Objects.isNull(sysMenuMapper.getMenuById(menuId))) {
            throw new BusinessException("角色不存在");
        }
    }

    private void validateRoleIds(List<Long> roleIds) {
        if (Objects.isNull(roleIds) || roleIds.isEmpty()) {
            throw new BusinessException("角色ID为空");
        }
        for (Long roleId : roleIds) {
            if (Objects.isNull(sysRoleMapper.getRoleById(roleId))) {
                throw new BusinessException("角色不存在，角色ID: " + roleId);
            }
        }
    }

    private void validateStatus(Integer status) {
        if (Objects.isNull(status)) {
            throw new BusinessException("状态值为空");
        }
        if (!DefaultStatusEnum.isValid(status)) {
            throw new BusinessException("无效的菜单状态");
        }
    }

    //------------------------ 工具方法  ------------------------
    // 将 DTO 转换为实体
    private SysMenu convertToSysMenu(SysMenuDTO menuDTO) {
        return ObjectConvertTool.originConvert(menuDTO, SysMenu.class);
    }

    // 将实体转换为 VO
    private SysMenuVO convertToSysMenuVO(SysMenu sysMenu) {
        return ObjectConvertTool.originConvert(sysMenu, SysMenuVO.class);
    }
}